/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package edu.capex.javacore.hilos;

import java.util.Random;

/**
 *
 * @author IK
 */
public class SyncBank {

    public static final int NACCOUNTS = 100;
    public static final double INITIAL_BALANCE = 1000;
    static boolean exit = false;
    Bank b;

    public static void main(String[] args) throws Exception {

        new SyncBank();
        System.in.read();
        System.exit(0);

    }

    public SyncBank()
    {
        b = new Bank(NACCOUNTS, INITIAL_BALANCE);

        for (int i = 0; i < NACCOUNTS; i++) {

            TransferRunnable r = new TransferRunnable(i, INITIAL_BALANCE);
            Thread t = new Thread(r);
            t.start();
        }
    }

    class TransferRunnable implements Runnable {

        private int fromAccount;
        private double maxAmount;
        private int repetitions;
        private int DELAY = 200;
        private Random r1;

        public void run() {

            try {

                while (!exit) {
                    int toAccount = r1.nextInt(b.size());
                    double amount = r1.nextInt((int) maxAmount);
                    b.transfer(fromAccount, toAccount, amount);
                    Thread.sleep(r1.nextInt(DELAY));

                }

            } catch (InterruptedException ex) {
            }
        }

        public TransferRunnable(int from, double max) {

            fromAccount = from;
            maxAmount = max;
            r1 = new Random();

        }
    }

    class Bank {

        private final double[] accounts;

        public Bank(int n, double initialBalance) {

            accounts = new double[n];
            for (int i = 0; i < accounts.length; i++) {

                accounts[i] = initialBalance;

            }

        }

        synchronized public void transfer(int from, int to, double amount) 
                
                throws InterruptedException {

                 System.out.println ("in" +Thread.currentThread().getName());
                 while( accounts [from] < amount )
                     
                     wait();
                 
                 
            accounts[from] -= amount;
            Thread.sleep(10);
            System.out.println(accounts[from] < 0 ? "A/C overdrawn!!!!" : "");
            System.out.printf("Transferred %10.2f from %d to %d%n", amount, from, to);
            accounts[to] += amount;

            System.out.printf("Total Balance %10.2f%n", getTotalBalance());


        }

        public double getTotalBalance() {

            double sum = 0;
            for (double a : accounts) {

                sum += a;

            }
            return sum;
        }

        public int size() {

            return accounts.length;
        }
    }
}
